package wili.a;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

/**
 * @author weilai2@163.com
 */
class Obj9a extends Obj9 {
	static void log(String msg, StringBuilder toBuf) {
		msg = msg.replace("\n", "\\n").replace("\r", "\\r");
		if (toBuf == null) {
			log(msg);
		} else {
			toBuf.append("\n" + msg);
		}
	}

	static void log(String msg) {
		++Obj9.times;
		if (msg.length() > 1000)
			msg = msg.substring(0, 500) + "...printSkip:" + (msg.length() - 1000) + " chars}..." + msg.substring(500);
		if (msg.contains("VatGrpSrc"))
			pause();
		System.out.println(msg);
	}

	static String strOf(Object obj) {
		return Objects.toString(obj).replaceAll("\\s+", " ");
	}

	public static int maxDiffNum = 10;

	@SuppressWarnings("all")
	static boolean findOrPrint00(String action, String dent, String name, Object obj, Map<Object, Integer> skipMap,
			StringBuilder toBuf) {
		// 需求，查找name=null, 查找name的值。

		if (obj == null) {
			log(dent + name + "=null", toBuf);
			return false;
		}
		int foundTimes = 0;
		try {
			Class<?> cls = obj.getClass();
			if (Coms5.isSimpleOrLangClass(cls)) {
				if (obj instanceof String) {
					//obj = obj.toString().replace("\r", "\\r").replace("\n", "\\n");
				}
				if (action == Act.find) {
					boolean print = false;
					if (Obj9.findName.isEmpty()) {
						if (Obj9.findValue.equals(obj))
							print = true;
					} else if (Obj9.findValue.isEmpty()) {
						if (Obj9.findName.equals(name))
							print = true;
					} else if (Obj9.findName.equals(name) && Obj9.findValue.equals(obj)) {
						print = true;
					}
					if (print) {
						System.out.println("\n  Obj9a.foundName: " + name + "=" + obj);
						return true;
					}
					pause();
				} else {
					if (Obj9.PrintNull || obj != null)
						log(dent + name + "=" + obj, toBuf);
				}
				return false;
			}
			final String DENT = "   ";
			if (dent.length() > 30)
				dent = "" + DENT;

			long id = System.identityHashCode(obj);
			Integer objId = skipMap.get(id);// 对象的hashCode或会变化，故用identityHashCode
			if (objId != null) {
				String idSt = Obj9.PrintID ? "id" + objId + "." : "..";
				if (Obj9.PrintID) {
					log(dent + name + ": ref(" + idSt + ")", toBuf);
				} else {
				}
				return false;
			}
			skipMap.put(id, objId = ++incID);
			String idSt = Obj9.PrintID ? "//" + id + "." : "";
			if (obj instanceof Collection) {
				Collection cc = (Collection) obj;
				int ind = -1;
				log(dent + name + ": [", toBuf);
				String dent2 = dent + DENT;
				for (Object ele : cc) {// 尝试遍历各子
					++ind;
					name = ("[" + ind + "]");
					if (findOrPrint00(action, dent2, name, ele, skipMap, toBuf))
						++foundTimes;
				}
				log(dent + "]", toBuf);
			} else if (obj instanceof Map) {
				Map<Object, Object> map = (Map) obj;
				if (map instanceof TreeMap) {
				} else if (map.size() > 0) {
					if ("asdf".isEmpty() && map.keySet().iterator().next() instanceof Comparable) {
						map = new TreeMap<>(map);
					}
				}
				log(dent + name + ": {" + idSt, toBuf);
				String dent2 = dent + DENT;
				for (Map.Entry<Object, Object> ent : map.entrySet()) {
					name = ent.getKey().toString();
					Object value = ent.getValue();
					if (findOrPrint00(action, dent2, name, value, skipMap, toBuf)) {
						++foundTimes;
					}
				}
				log(dent + "}", toBuf);
			} else if (cls.isArray()) {
				if (Coms5.isSimpleOrLangClass(cls.getComponentType())) {
					log(dent + name + "=" + Coms5.stringOfArray(obj) + "," + idSt, toBuf);
				} else {
					log(dent + name + ": [" + idSt, toBuf);
					int len = Array.getLength(obj);
					dent += DENT;
					for (int i = 0; i < len; i++) {
						Object ele = Array.get(obj, i);
						name = ("[" + i + "]");
						if (findOrPrint00(action, dent, name, ele, skipMap, toBuf))
							++foundTimes;
					}
					log(dent + "]", toBuf);
				}
			} else {
				Map<String, Object> map = Coms5.valueMapOfObject(obj);
				{
					String cname = obj.getClass().getSimpleName();
					int len = toBuf == null ? -1 : toBuf.length();
					log(dent + name + "=" + cname + " {" + idSt, toBuf);
					String dent2 = dent + DENT;
					for (Map.Entry<String, Object> ent : map.entrySet()) {
						name = ent.getKey().toString();
						Object value = ent.getValue();
						if (findOrPrint00(action, dent2, name, value, skipMap, toBuf))
							++foundTimes;
					}
					log(dent + "}//" + cname, toBuf);
				}
			}
			if (foundTimes > 0)
				return true;
			return false;
		} catch (Throwable e) {
			e.printStackTrace();
			return foundTimes > 0;
		}
	}

	static void pause() {
	}
}
